package com.smasher.update.component.download.ok

import android.content.Context
import android.net.Uri
import android.os.Environment
import android.util.Log
import com.liulishuo.okdownload.DownloadTask
import com.liulishuo.okdownload.SpeedCalculator
import com.liulishuo.okdownload.StatusUtil
import com.liulishuo.okdownload.StatusUtil.Status
import com.liulishuo.okdownload.core.breakpoint.BlockInfo
import com.liulishuo.okdownload.core.breakpoint.BreakpointInfo
import com.liulishuo.okdownload.core.cause.EndCause
import com.liulishuo.okdownload.core.listener.DownloadListener4WithSpeed
import com.liulishuo.okdownload.core.listener.assist.Listener4SpeedAssistExtend
import com.smasher.update.component.download.DownloadDelegate
import com.smasher.update.component.download.DownloadFinishListener
import com.smasher.update.component.download.DownloadHelper
import com.smasher.update.component.parse.ParseDelegate
import com.smasher.update.provider.FileProvider7Util
import java.io.File
import java.lang.ref.WeakReference
import java.math.BigDecimal
import java.math.RoundingMode
import kotlin.math.abs


class DownloadImplOk(context: Context) : DownloadDelegate {

    private val downloadHelper = DownloadHelper(context)

    // 回调系统
    private var finishListener: DownloadFinishListener? = null

    // 下载控制
    private var downloadTask: DownloadTask? = null

    // 状态跟踪
    private var downloadProgress: Int = 0

    // 在类成员变量区增加记录变量
    private var lastNotifiedProgress = -1 // 初始值设为-1确保首次必定通知


    private var weakReference = WeakReference<Context>(context)


    override fun startDownload(parseDelegate: ParseDelegate): Long {
        val downloadUrl = parseDelegate.getDownLoadUrl()
        val filename = createTargetName()
        val downloadDirectory =
            weakReference.get()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
        if (downloadDirectory != null) {
            deleteSame(downloadDirectory, filename)
            downloadTask = DownloadTask.Builder(downloadUrl, downloadDirectory)
                .setConnectionCount(3)
                .setFilename(filename) // the minimal interval millisecond for callback progress
                .setMinIntervalMillisCallbackProcess(300) // do re-download even if the task has already been completed in the past.
                .setPassIfAlreadyCompleted(false).build()
            downloadTask?.enqueue(downloadListener4)
        }
        return downloadTask?.id?.toLong() ?: 0L
    }


    override fun addDownloadFinishListener(listener: DownloadFinishListener) {
        finishListener = listener
    }

    override fun getDownloadUriById(id: Long): Uri? {
        val downloadDirectory =
            weakReference.get()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
        val filename = createTargetName()
        val file = File(downloadDirectory, filename)
        val uri = FileProvider7Util.getUriForFile(weakReference.get(), file)
        return uri
    }

    override fun queryFinishedById(id: Long): Boolean {
        return downloadTask?.let {
            StatusUtil.getStatus(it) == Status.COMPLETED
        } == true
    }

    private fun deleteSame(downloadDirectory: File?, filename: String) {
        try {
            val target = File(downloadDirectory, filename)
            if (target.exists()) {
                val isDeleted = target.delete()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }


    private fun createTargetName(): String {
        return ("TARGET_${downloadHelper.versionCode}").toString() + ".apk"
    }

    private val downloadListener4 = object : DownloadListener4WithSpeed() {
        override fun taskStart(task: DownloadTask) {
            Log.i(TAG, "taskStart: ")
            downloadProgress = 0
        }

        override fun connectStart(
            task: DownloadTask,
            blockIndex: Int,
            requestHeaderFields: MutableMap<String, MutableList<String>>
        ) {
            Log.i(TAG, "connectStart: ")
        }

        override fun connectEnd(
            task: DownloadTask,
            blockIndex: Int,
            responseCode: Int,
            responseHeaderFields: MutableMap<String, MutableList<String>>
        ) {
            Log.i(TAG, "connectEnd: ")
        }

        override fun taskEnd(
            task: DownloadTask,
            cause: EndCause,
            realCause: java.lang.Exception?,
            taskSpeed: SpeedCalculator
        ) {
            Log.i(TAG, "taskEnd: ")
            val isFinished = when (StatusUtil.getStatus(task)) {
                Status.COMPLETED -> true
                else -> false
            }
            weakReference.get()?.let {
                if (isFinished) {
                    downloadProgress = 100
                    downloadHelper.createNotificationProgress(it, downloadProgress, "下载完成")
                } else {
                    downloadHelper.createNotificationProgress(it, downloadProgress, "下载失败")
                }
            }

            Log.i(TAG, "taskEnd: isCompleted $isFinished")
            finishListener?.onDownload(task.id.toLong())
        }

        override fun infoReady(
            task: DownloadTask,
            info: BreakpointInfo,
            fromBreakpoint: Boolean,
            model: Listener4SpeedAssistExtend.Listener4SpeedModel
        ) {
            Log.i(TAG, "infoReady: ")
        }

        override fun progressBlock(
            task: DownloadTask,
            blockIndex: Int,
            currentBlockOffset: Long,
            blockSpeed: SpeedCalculator
        ) {
            Log.i(TAG, "progressBlock: blockIndex $blockIndex")
        }

        override fun progress(task: DownloadTask, currentOffset: Long, taskSpeed: SpeedCalculator) {
            val breakpoint = task.info
            val total = breakpoint?.totalLength ?: 0L
            calculateProgress(currentOffset, total)
        }

        override fun blockEnd(
            task: DownloadTask,
            blockIndex: Int,
            info: BlockInfo?,
            blockSpeed: SpeedCalculator
        ) {
            Log.i(TAG, "blockEnd: ")
        }
    }

    private fun calculateProgress(current: Long, total: Long) {
        if (total != 0L) {
            try {
                val progressDecimal = BigDecimal(current.toString())
                val totalDecimal = BigDecimal(total.toString())
                val percentCalculate =
                    progressDecimal.divide(totalDecimal, 2, RoundingMode.HALF_UP)
                val percentResult = percentCalculate.multiply(BigDecimal("100"))
                val progress = percentResult.toInt()
                Log.i(TAG, "progress: $progress%")
                if (abs(progress - lastNotifiedProgress) >= NOTIFICATION_THRESHOLD || progress == 100) {
                    val content = "下载中（$progress%）"
                    downloadProgress = progress
                    weakReference.get()?.let {
                        downloadHelper.createNotificationProgress(it, progress, content)
                    }
                }

            } catch (e: Exception) {
                Log.e(TAG, "progress: ", e)
            }
        }
    }

    override fun release() {
        weakReference.clear()
    }

    companion object {
        const val TAG = "DownloadImplOK"
        const val NOTIFICATION_THRESHOLD = 3 // 5%变化阈值
    }
}